/*
 * temp_control.c
 *
 *  Created on: 2021年12月1日
 *      Author: CameronLee
 */

#include "temp_control.h"

PID temp_stabilization;
static float Last_Temp =0 ;

volatile float Target_Temperature = 60;

volatile float Dynamic_Compensation_Value = 0;

extern osMessageQueueId_t MeaTempHandle;
extern osEventFlagsId_t SysStatusFlagHandle;
extern osMutexId_t Control_MutexHandle;




//加热信号为低电平有效，若失能PWM输出 则会导致被拉低
//因此停止加热就是拉高PWM的输出
static void Stop_Heat(void)
{
	__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,0);
}


//第一个 PI控制 P值大 加热到 目标值 - 10
void Temperature_Heating(float deta_T)
{
	float  pid_out;

	//快速加热阶段 比例就够了 但也可进一步完善提升
	pid_out = deta_T * deta_T*0.5+10;
	if(pid_out > MAX_P){
		pid_out = MAX_P;
	}
	if(pid_out < 0){
		pid_out = 0;
	}

	//实施加热
	UI_Heat_P = pid_out;
	osEventFlagsSet(SysStatusFlagHandle,0x02);
	__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,(uint16_t)(250*pid_out));

	}

static float Dynamic_Compensation(float deta_T,float Deta_T)
{
	float adjustment_value,deta_enr_box_temp;

	osMutexAcquire(Control_MutexHandle,1000); //上锁

	deta_enr_box_temp = Deta_Enr_BOX;

	adjustment_value = deta_T*0.014 - Deta_T*0.026 - deta_enr_box_temp*0.12 + 0.5;

	osMutexRelease(Control_MutexHandle); //解锁

	return (adjustment_value +Dynamic_Compensation_Value);
}

//第二个 fuzzyPID 精准控温程序
static void Temperature_Balance(float deta_T,float Deta_T)
{
	static uint8_t i =0;
	float  pid_out;
	if (i == 50) {
		//也可以把这个放到SV中
		Fuzzy_PID_Arg_Init(&temp_stabilization);
	}
	pid_out = Fuzzy_PID_Contrl(&temp_stabilization,deta_T);

	//动态补偿
	pid_out+= Dynamic_Compensation(deta_T,Deta_T);

	if(pid_out > MAX_P){
		pid_out = MAX_P;
	}
	if(pid_out < 0){
		pid_out = 0;
	}
	//启动加热
	UI_Heat_P = pid_out;
	osEventFlagsSet(SysStatusFlagHandle,0x02);
	__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,(uint16_t)(250*pid_out));

	i++;
}


//周期性挂起加热任务！挂起多长时间？
static void Heat_TASK_Wait_Time(uint16_t x)
{
	uint16_t i;
	//停止加热任务
	Stop_Heat();

	for (i = 0; i < x; ++i){
		osDelay(1000);
		if(osMessageQueueGetMsgSize (MeaTempHandle)){
			osMessageQueueReset(MeaTempHandle);
		}
	}
}

void Temerature_Control_Task(void)
{
	float deta_T,Deta_T;
	uint32_t Flag;
	uint16_t stop_num;
	static uint8_t satisfy_time;
	Flag = osEventFlagsGet(SysStatusFlagHandle);
	while(osMessageQueueGet(MeaTempHandle,&deta_T,NULL,1000));

	//获取当前温度数据 暂存于 deta_T
	//进入临界区
	//taskENTER_CRITICAL();
	Deta_T = deta_T - Last_Temp;
	Last_Temp  = deta_T;
	deta_T = Target_Temperature - deta_T;
	//taskEXIT_CRITICAL();
	//Deta_T  >0 升温   			<0 降温      ------------> 温度变化趋势
	//deta_T  >0 待加热 			<0 超调		 ------------> 误差

	if(deta_T > 0){
		if((deta_T < 5)&&(deta_T > 3)){
			osEventFlagsSet(SysStatusFlagHandle,0x80);
		}else{
			osEventFlagsSet(SysStatusFlagHandle,0x40);
		}
	}else if(deta_T == 0){
		if(satisfy_time==Satisfy_Time){
			osEventFlagsSet(SysStatusFlagHandle,0x10000);
		}else
			satisfy_time++;
	}else{
		deta_T = -deta_T;
		if ((deta_T >= 3)&&(deta_T < 5)) {
			osEventFlagsSet(SysStatusFlagHandle,0x100);
		}else if((deta_T >= 5)&&(deta_T < 10)){
			osEventFlagsSet(SysStatusFlagHandle,0x200);
		}else if(deta_T >= 10){
			osEventFlagsSet(SysStatusFlagHandle,0x400);
		}
		deta_T = -deta_T;
	}


	if (Deta_T < 0) {
		osEventFlagsSet(SysStatusFlagHandle,0x800);
	}else if(Deta_T == 0){
		osEventFlagsSet(SysStatusFlagHandle,0x1000);
	}else if(Deta_T>0){
		if(Deta_T < 0.1875){
			osEventFlagsSet(SysStatusFlagHandle,0x2000);
		}else{
			osEventFlagsSet(SysStatusFlagHandle,0x4000);
		}
	}

	if (READ_BIT(Flag,0x8000)) {
		stop_num = Heating_Stop_Time_Num;
		Heat_TASK_Wait_Time(stop_num);
	}else{
		if(deta_T	> 10){
			if (Deta_T < 0.625) {
				Temperature_Heating(deta_T);
			} else {
				Stop_Heat();
				osDelay(1000+(uint32_t)(Deta_T*10000));
			}
		}else if(deta_T <= 10){
			Temperature_Balance(deta_T,Deta_T);
		}

	}

}

